﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using AStar.Collections;
using AStar.Class;

namespace AStar
{
    [Serializable]
    class MyHash<K, V>
        where K : IComparable
    {
        MyList<MyWrapper<K, V>>[] values = new MyList<MyWrapper<K, V>>[68];

        public V this[K key]
        {
            set
            {
                Add(key, value);
            }
            get
            {
                V re = default(V);
                int index = GetHash(key);
                if (values[index] != null)
                {
                    for (int i = 0; i < values[index].Count(); i++)
                    {
                        if (key.Equals(values[index].Get(i).Key))
                        {
                            re = values[index].Get(i).Value;
                            break;
                        }
                    }
                }
                return re;
            }
        }

        private void Add(K key, V value)
        {
            if (Exists(key))
            {
                int index = GetHash(key);
                if (values[index] != null)
                {
                    for (int i = 0; i < values[index].Count(); i++)
                    {
                        if (key.Equals(values[index].Get(i).Key))
                        {
                            values[index].Get(i).Value = value;
                            break;
                        }
                    }
                }
            }
            else
            {
                MyWrapper<K, V> leAdd = new MyWrapper<K, V>(key, value);
                if (values[GetHash(key)] == null)
                {
                    values[GetHash(key)] = new MyList<MyWrapper<K, V>>();
                }
                values[GetHash(key)].Add(leAdd);
            }
        }

        private int GetHash(K key)
        {
            int index = key.GetHashCode() % 68;
            if (index < 0)
            {
                index *= -1;
            }
            return index;
        }

        public bool Exists(K key)
        {
            bool re = false;
            int index = GetHash(key);
            if (values[index] != null)
            {
                for (int i = 0; i < values[index].Count(); i++)
                {
                    if (key.Equals(values[index].Get(i).Key))
                    {
                        re = true;
                        break;
                    }
                }
            }
            return re;
        }

        public void Remove(K key)
        {
            this[key] = default(V);
        }

        public MyList<K> Keys()
        {
            MyList<K> re = new MyList<K>();
            for (int i = 0; i < values.Length; i++)
            {
                if (values[i] != null)
                {
                    for (int j = 0; j < values[i].Count(); j++)
                    {
                        re.Add(values[i].Get(j).Key);
                    }
                }
            }
            return re;
        }

        /*public bool exists(K key)
        {
            bool re = false;
            MyList<K> keys = Keys();
            for (int i = 0; i < keys.Count(); i++)
            {
                if (keys.get(i).CompareTo(key) == 0)
                {
                    re = true;
                    break;
                }
            }
            return re;
        }*/
    }

    [Serializable]
    class MyWrapper<K, V> : IComparable
        where K : IComparable
    {
        private K key;
        private V value;

        public V Value
        {
            get { return this.value; }
            set { this.value = value; }
        }

        public K Key
        {
            get { return key; }
            set { key = value; }
        }


        public MyWrapper(K key, V value)
        {
            this.key = key;
            this.value = value;
        }

        public MyWrapper()
        {

        }

        public int CompareTo(object obj)
        {
            return key.CompareTo((K)obj);
        }
    }
}
